#![allow(dead_code)]

struct StructLrn {}

impl StructLrn {
    pub fn hello() {
        println!("Struct learning!");
    }
}

#[cfg(test)]
mod tests {
    // use super::*;

    #[test]
    #[allow(unused_variables)]
    fn three_methods() {
        // NOTE: 单元结构体
        // 用作标记,只实现traits,不存储数据
        struct Unit;

        impl Unit {
            fn hello() {
                println!("Unit struct!");
            }
        }

        Unit::hello();

        // NOTE: 元组结构体
        #[derive(Debug)]
        struct Point(i32, i32, i32);
        #[derive(Debug)]
        struct RgbColor(u8, u8, u8);
        #[derive(Debug)]
        struct Inches(i32);
        #[derive(Debug)]
        struct Mag<'a>(i32, &'a str, String);
        #[derive(Debug)]
        struct UnsizeStruct<T, U, B: ?Sized>(T, U, B); //只有最后一个field可以是不确定, 只能一个

        let p1 = Point(1, 2, 3);
        let Point(x, y, z) = p1;
        let p_0 = p1.0;
        let unsized_struct = UnsizeStruct("hello", [1, 2, 3], p1);

        println!("{:?}", unsized_struct);

        assert_eq!(x, 1);
        assert_eq!(p_0, 1);

        // NOTE: 常规结构体
        struct Regular {
            field1: i32,
            field2: String,
            pub field3: bool,
        }

        let example = Regular {
            field1: 1,
            field2: String::from("hello"),
            field3: true,
        };

        assert_eq!(example.field1, 1);
    }

    #[test]
    fn instantiation() {
        struct User {
            username: String,
            email: String,
            sign_in_count: u64,
            active: bool,
        }

        impl User {
            fn new(username: String, email: String) -> User {
                User {
                    username,
                    email,
                    sign_in_count: 1,
                    active: true,
                }
            }
        }

        let user1 = User::new(String::from("Tom"), String::from("tom@163.com"));

        let user2 = User {
            username: String::from("Alice"),
            email: String::from("Alice@msn.com"),
            // NOTE: 结构体实例化的快捷方式 ..user1
            ..user1
        };

        assert_eq!(&user2.username, "Alice");
        assert_eq!(user2.sign_in_count, 1);
    }

    #[test]
    fn ref_struct() {
        #[derive(Debug, PartialEq)]
        struct Unit;
        impl Unit {
            fn call(&self) {
                println!("struct Unit called!");
            }
        }

        let a = Unit;
        let b = &a;
        let c = &b;

        assert_eq!(a, **c);
        (**c).call();
    }
}
